Skip to content

US Core profile support, unified getter/setter API, validate() with errors/warnings and must-support#102

Merged
ryukzak merged 27 commits intomainfrom
us-core-profile-support
Mar 12, 2026
Merged

US Core profile support, unified getter/setter API, validate() with errors/warnings and must-support#102
ryukzak merged 27 commits intomainfrom
us-core-profile-support

Conversation

@ryukzak
Copy link
Copy Markdown
Collaborator

@ryukzak ryukzak commented Mar 12, 2026

Summary

  • Add US Core IG profile generation (Patient, Observation vitals/BP/bodyweight, Race/Ethnicity/Sex/TribalAffiliation/InterpreterNeeded extensions)
  • Refactor profile generation: extract profile-slices, profile-extensions, profile-validation modules
  • Add constrained choice detection and deduplicate extensions by canonical URL
  • Add writer infrastructure: ifElseChain, lineWidth, naming helpers
  • Split from()/apply() factory methods
    • from(resource) — validates meta.profile + runs validate(), throws on errors
    • apply(resource) — stamps meta.profile without validation, for incremental construction
  • Multi-form extension setters — accept flat input, profile instance, or raw FHIR Extension
  • Extension getters with overloaded mode: flat (typed object), profile (profile instance), raw (FHIR Extension)
  • Unify slice and extension getter/setter API with overloaded mode parameter (flat/raw/profile/extension)
  • Remove toProfile(), combine imports by module, remove dead helpers
  • Return { errors, warnings } from validate() instead of string[]
    • Extensible binding mismatches reported as warnings
    • Must-support field population reported as warnings (non-required fields only)
  • Update docs, posts, and README for new API shape

Before — from() was a simple wrapper without validation:

const profile = observation_bodyweightProfile.from(obs);

After — from() validates, apply() stamps without validation:

const profile = USCorePatientProfile.from(obs);   // throws if meta.profile missing or validate() errors
const profile = USCorePatientProfile.apply(obs);   // stamps meta.profile, no validation

Before — extension setters accepted only one form:

patient.setRace(raceExtension);

After — multi-form setters accept flat input, profile instance, or raw Extension:

patient.setRace({ ombCategory: { code: "2028-9" }, text: "Asian" });       // flat input
patient.setRace(USCoreRaceExtensionProfile.create({ ... }));                // profile instance
patient.setRace({ url: "http://.../us-core-race", extension: [...] });      // raw Extension

After — extension getters with mode overloads:

patient.getRace();           // flat: { ombCategory: ..., text: "Asian" }
patient.getRace("profile");  // USCoreRaceExtensionProfile instance
patient.getRace("raw");      // raw FHIR Extension

Before — validate() returned a flat error array, no must-support awareness:

const errors: string[] = bp.validate();

After — structured result with errors and warnings:

const { errors, warnings } = bp.validate();
// errors: ["observation_bp: required field 'effective' is missing"]
// warnings: ["observation_bp: must-support field 'dataAbsentReason' is not populated"]

Before — separate getter methods per mode:

bp.getSystolicBP();     // flat
bp.getSystolicBPRaw();  // raw

After — overloaded single getter:

bp.getSystolicBP();       // flat (default)
bp.getSystolicBP("raw");  // raw FHIR element

ryukzak added 4 commits March 12, 2026 09:28
- Add ConstrainedChoiceInfo type and constrainedChoice() index method
- Export isChoiceDeclarationField and isChoiceInstanceField from utils
- Deduplicate profile extensions by url:path in extension processing
- Add ifElseChain() and tsImport() with auto-wrapping to TypeScript writer
- Add lineWidth option for long import line splitting
- Add fieldTsType() helper to eliminate repeated type resolution pattern
- Refactor method naming to suffix-based resolution with collision handling
- Make indent()/deindent() protected in base Writer
- Add resolveExtensionInput(), isRawExtensionInput(), getExtensionValue()
- Add isExtension() type guard with optional url parameter
- Add ExtensionProfileLike type for profile instance detection
- Enhance extractComplexExtension() with generics
- Extract extension generation to profile-extensions.ts (multi-form setters,
  getter modes, input resolution with ifElseChain)
- Extract slice generation to profile-slices.ts
- Extract validation generation to profile-validation.ts
- Split from() into validating from() and non-validating apply()
- Cache detectFieldOverrides, hoist polymorphicBaseNames, inline helpers
ryukzak added 17 commits March 12, 2026 18:03
- Add profile tests: patient (extensions, multi-form setters, factory methods),
  blood pressure (component slices), body weight (demo)
- Add US Core snapshot tests to typescript.test.ts
- Add release announcement post and update example README
- Update demo scripts to use static factory methods
- Slice setters accept union of flat input or raw FHIR type, using
  matchesValue() to discriminate
- Slice getters use overloaded mode parameter ('flat' | 'raw') instead
  of separate getXxx()/getXxxRaw() methods
- Rename extension getter mode 'extension' → 'raw' to match slice API
- Rename 'input' mode → 'flat' for both slice and extension getters
- Rename type suffixes: SliceInput → SliceFlat, Input → Flat,
  InputRaw → Raw
- Add sliceGetterDefault option to TypeScriptOptions
@ryukzak ryukzak force-pushed the us-core-profile-support branch from 3682d19 to 65a5e8a Compare March 12, 2026 17:05
@ryukzak ryukzak merged commit b81c7ae into main Mar 12, 2026
31 checks passed
@ryukzak ryukzak deleted the us-core-profile-support branch March 12, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants